Added documentation about how to use the unit test runner.
[adiumx.git] / Plugins / Purple Service / AMPurpleJabberAdHocServer.m
blob495baeb02a11e8fb724d0bfc9798590cb24deaed
1 #import "AMPurpleJabberAdHocServer.h"
2 #import "ESPurpleJabberAccount.h"
3 #import "AMPurpleJabberFormGenerator.h"
4 #import "AMPurpleJabberAdHocCommand.h"
5 #include <Libpurple/jabber.h>
7 @interface AMPurpleJabberAdHocServer (PRIVATE)
8 - (BOOL)receivedCommand:(xmlnode*)command from:(NSString*)jid iqid:(NSString*)iqid;
9 - (void)addCommandsToXML:(xmlnode*)xml;
10 @end
12 @implementation AMPurpleJabberAdHocServer
14 static void AMPurpleJabberAdHocServer_received_data_cb(PurpleConnection *gc, xmlnode **packet, gpointer this) {
15         AMPurpleJabberAdHocServer *self = this;
16         PurpleAccount *account = [[self account] purpleAccount];
17         if(account->gc == gc) {
18                 if(strcmp((*packet)->name,"iq"))
19                         return;
20                 const char *type = xmlnode_get_attrib(*packet,"type");
21                 if(!type || strcmp(type,"set"))
22                         return; // doesn't talk to us, probably the user interacting with some other adhoc node
23                 const char *from = xmlnode_get_attrib(*packet,"from");
24                 const char *iqid = xmlnode_get_attrib(*packet,"id");
25                 xmlnode *command = xmlnode_get_child_with_namespace(*packet,"command","http://jabber.org/protocol/commands");
26                 if(command) {
27                         BOOL handled = [self receivedCommand:command
28                                                                                         from:from?[NSString stringWithUTF8String:from]:nil
29                                                                                         iqid:iqid?[NSString stringWithUTF8String:iqid]:nil];
30                         if(handled) {
31                                 xmlnode_free(*packet);
32                                 *packet = NULL;
33                         }
34                 }
35         }
38 /* we have to catch the reply to a disco#info for http://jabber.org/protocol/commands and insert our nodes */
39 static void xmlnode_sent_cb(PurpleConnection *gc, xmlnode **packet, gpointer this) {
40         xmlnode *xml = *packet;
41         AMPurpleJabberAdHocServer *self = this;
42         PurpleAccount *account = [[self account] purpleAccount];
43         if(xml && account->gc == gc) {
44                 if(!strcmp(xml->name,"iq")) {
45                         const char *tostr = xmlnode_get_attrib(xml,"to");
46                         if(tostr) {
47                                 NSString *to = [NSString stringWithUTF8String:tostr];
48                                 NSRange slash = [to rangeOfString:@"/"];
49                                 if(slash.location != NSNotFound) {
50                                         NSString *barejid = [to substringToIndex:slash.location];
51                                         if([barejid isEqualToString:[[self account] UID]]) {
52                                                 const char *type = xmlnode_get_attrib(xml,"type");
53                                                 if(type && !strcmp(type,"result")) {
54                                                         xmlnode *query = xmlnode_get_child_with_namespace(xml,"query","http://jabber.org/protocol/disco#items");
55                                                         if(query) {
56                                                                 const char *node = xmlnode_get_attrib(query,"node");
57                                                                 if(node && !strcmp(node,"http://jabber.org/protocol/commands"))
58                                                                         [self addCommandsToXML:query];
59                                                         }
60                                                 }
61                                         }
62                                 }
63                         }
64                 }
65         }
68 + (void)initialize {
69         jabber_add_feature("adiumcmd", "http://jabber.org/protocol/commands", NULL);
72 - (id)initWithAccount:(ESPurpleJabberAccount*)_account {
73         if((self = [super init])) {
74                 account = _account;
75                 commands = [[NSMutableDictionary alloc] init];
76                 
77                 PurplePlugin *jabber = purple_find_prpl("prpl-jabber");
78         if (!jabber) {
79             AILog(@"Unable to locate jabber prpl");
80             [self release];
81             return nil;
82         }
84                 purple_signal_connect(jabber, "jabber-receiving-xmlnode", self,
85                               PURPLE_CALLBACK(AMPurpleJabberAdHocServer_received_data_cb), self);
86         purple_signal_connect(jabber, "jabber-sending-xmlnode", self,
87                               PURPLE_CALLBACK(xmlnode_sent_cb), self);
88         }
89         return self;
92 - (void)dealloc {
93         purple_signals_disconnect_by_handle(self);
94         [commands release];
95         [super dealloc];
98 - (void)addCommand:(NSString*)node delegate:(id)delegate name:(NSString*)name {
99         [commands setObject:[NSDictionary dictionaryWithObjectsAndKeys:
100                                 [NSValue valueWithNonretainedObject:delegate],@"delegate",
101                                 name, @"name",
102                                 nil] forKey:node];
105 - (void)removeCommand:(NSString*)node {
106         [commands removeObjectForKey:node];
109 - (ESPurpleJabberAccount*)account {
110         return account;
113 - (void)addCommandsToXML:(xmlnode*)xml {
114         NSEnumerator *e = [commands keyEnumerator];
115         NSString *node;
116         JabberStream *js = purple_account_get_connection([[self account] purpleAccount])->proto_data;
117         char *jid = g_strdup_printf("%s@%s/%s", js->user->node, js->user->domain, js->user->resource);
118         
119         while((node = [e nextObject])) {
120                 xmlnode *item = xmlnode_new_child(xml, "item");
121                 xmlnode_set_attrib(item,"jid",jid);
122                 xmlnode_set_attrib(item,"name",[[[commands objectForKey:node] objectForKey:@"name"] UTF8String]);
123                 xmlnode_set_attrib(item,"node",[node UTF8String]);
124         }
125         g_free(jid);
128 - (BOOL)receivedCommand:(xmlnode*)command from:(NSString*)jid iqid:(NSString*)iqid {
129         // verify that it's the same bare jid this command was received from
130         if(!jid)
131                 return NO;
132         NSRange slash = [jid rangeOfString:@"/"];
133         if(slash.location == NSNotFound || ![[jid substringToIndex:slash.location] isEqualToString:[account UID]])
134                 return NO;
135         
136         const char *node = xmlnode_get_attrib(command,"node");
137         
138         if(node) {
139                 id delegate = [[commands objectForKey:[NSString stringWithUTF8String:node]] objectForKey:@"delegate"];
140                 if(delegate && [[delegate nonretainedObjectValue] respondsToSelector:@selector(adHocServer:executeCommand:)]) {
141                         AMPurpleJabberAdHocCommand *cmd = [[AMPurpleJabberAdHocCommand alloc] initWithServer:self command:command jid:jid iqid:iqid];
142                         [[delegate nonretainedObjectValue] adHocServer:self executeCommand:cmd];
143                         [cmd release];
144                         return YES;
145                 }
146         }
147         return NO;
150 @end